import 'winston-daily-rotate-file';
import { Injectable, LoggerService } from '@nestjs/common';
import { Logger, createLogger, format, transports } from 'winston';

import { env } from '../../settings'


@Injectable()
export class CustomerLogger implements LoggerService {
    private logger: Logger;

    get getFormat() {
        return format.printf(({ level, message, context, timestamp, extra }) => {
            return `${timestamp} - ${level} - ${context} - ${message} - extra: ${JSON.stringify(extra)}`;
        });
    }

    private getDailyRotateFile() {
        const myFormat = this.getFormat;
        return new transports.DailyRotateFile({
            dirname: 'logs',
            filename: 'application-%DATE%.log',
            datePattern: 'YYYY-MM-DD',
            zippedArchive: true,
            maxSize: '10m',
            maxFiles: '30d',
            format: format.combine(
                format.timestamp({
                    format: 'YYYY-MM-DD HH:mm:ss',
                }),
                myFormat
            )
        });
    }

    private getTransports() {
        let result = [new transports.Console()];
        if (env.isProduction) {
            const dailyRotateFile = this.getDailyRotateFile() as any;
            result.push(dailyRotateFile);
        }
        return result;
    }

    constructor() {
        this.logger = createLogger({
            format: format.combine(
                format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
                this.getFormat
            ),
            transports: this.getTransports()
        });
    }

    private warpParams(params: any) {
        let context: string, extra: any;
        if (!Array.isArray(params)) {
            context = params
        } else {
            [context, extra] = params
        }

        extra = extra ? extra : {}
        extra = Object.assign({
            version: env.VERSION,
        }, extra)

        return {
            context,
            extra
        }
    }

    private getLogMessage(message: string, params: any[]) {
        const paramMessage = this.warpParams(params)
        return Object.assign({
            message
        }, paramMessage)
    }

    log(message: string, params: any[]) {
        const logMsg = this.getLogMessage(message, params)
        this.logger.info(logMsg);
    }

    info(message: string, params: any[]) {
        const logMsg = this.getLogMessage(message, params)
        this.logger.info(logMsg);
    }

    error(message: string, params: any[]) {
        const logMsg = this.getLogMessage(message, params)
        this.logger.error(logMsg);
    }

    warn(message: string, params: any[]) {
        const logMsg = this.getLogMessage(message, params)
        this.logger.warn(logMsg);
    }

    debug(message: string, params: any[]) {
        const logMsg = this.getLogMessage(message, params)
        this.logger.debug(logMsg);
    }
}
